home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / program / gcc / gcc270-b.lha / gnu / ManualBrowser / DynamicHost.c < prev    next >
C/C++ Source or Header  |  1994-12-07  |  21KB  |  842 lines

  1. /************************************************************************/
  2. /*                                                                      */
  3. /*  Copyright (C) 1994  Christian Stieber                               */
  4. /*                                                                      */
  5. /* This program is free software; you can redistribute it and/or modify */
  6. /* it under the terms of the GNU General Public License as published by */
  7. /* the Free Software Foundation; either version 2 of the License, or    */
  8. /* (at your option) any later version.                                  */
  9. /*                                                                      */
  10. /* This program is distributed in the hope that it will be useful,      */
  11. /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
  12. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
  13. /* GNU General Public License for more details.                         */
  14. /*                                                                      */
  15. /* You should have received a copy of the GNU General Public License    */
  16. /* along with this program; if not, write to the Free Software          */
  17. /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            */
  18. /*                                                                      */
  19. /************************************************************************/
  20. /*                                                                      */
  21. /* Author address:                                                      */
  22. /*   Christian Stieber                                                  */
  23. /*   Konradstraße 41                                                    */
  24. /*   D-85055 Ingolstadt                                                 */
  25. /*   (Germany)                                                          */
  26. /*   Phone: 0841-59896                                                  */
  27. /*                                                                      */
  28. /************************************************************************/
  29.  
  30. #ifndef V39
  31. #define CreatePool LibCreatePool
  32. #define DeletePool LibDeletePool
  33. #define AllocPooled LibAllocPooled
  34. #define FreePooled LibFreePooled
  35. #endif
  36.  
  37. #ifndef DOS_DOSEXTENS_H
  38. #include <dos/dosextens.h>
  39. #endif
  40.  
  41. #ifndef DOS_EXALL_H
  42. #include <dos/exall.h>
  43. #endif
  44.  
  45. #ifndef INTUITION_INTUITION_H
  46. #include <intuition/intuition.h>
  47. #endif
  48.  
  49. #ifndef LIBRARIES_AMIGAGUIDE_H
  50. #include <libraries/amigaguide.h>
  51. #endif
  52.  
  53. #ifndef WORKBENCH_STARTUP_H
  54. #include <workbench/startup.h>
  55. #endif
  56.  
  57. #ifndef WORKBENCH_WORKBENCH_H
  58. #include <workbench/workbench.h>
  59. #endif
  60.  
  61. #ifndef __GNUC__
  62. #ifndef CLIB_EXEC_PROTOS_H
  63. #include <clib/exec_protos.h>
  64. #endif
  65.  
  66. #ifndef CLIB_DOS_PROTOS_H
  67. #include <clib/dos_protos.h>
  68. #endif
  69.  
  70. #ifndef CLIB_UTILITY_PROTOS_H
  71. #include <clib/utility_protos.h>
  72. #endif
  73.  
  74. #ifndef CLIB_INTUITION_PROTOS_H
  75. #include <clib/intuition_protos.h>
  76. #endif
  77.  
  78. #ifndef CLIB_ICON_PROTOS_H
  79. #include <clib/icon_protos.h>
  80. #endif
  81.  
  82. #ifndef CLIB_AMIGAGUIDE_PROTOS_H
  83. #include <clib/amigaguide_protos.h>
  84. #endif
  85.  
  86. #include <pragmas/exec_pragmas.h>
  87. #include <pragmas/dos_pragmas.h>
  88. #include <pragmas/intuition_pragmas.h>
  89. #include <pragmas/utility_pragmas.h>
  90. #include <pragmas/icon_pragmas.h>
  91. #include <pragmas/amigaguide_pragmas.h>
  92. #endif
  93.  
  94. #include <string.h>
  95.  
  96. #include "Globals.h"
  97.  
  98. /************************************************************************/
  99.  
  100. #ifdef __GNUC__
  101.  
  102. #include "Inlines.h"
  103.  
  104. #ifndef V39
  105. APTR AllocPooled (APTR, ULONG);
  106. void FreePooled (APTR, APTR, ULONG);
  107. APTR CreatePool (ULONG, ULONG, ULONG);
  108. void DeletePool (APTR);
  109. #endif
  110.  
  111. #endif /* __GNUC__ */
  112.  
  113. /************************************************************************/
  114.  
  115. #define MESSAGE_NAME    ".Message"
  116. #define CONFIG_NAME     ".Config"
  117.  
  118. /************************************************************************/
  119.  
  120. static char AboutText[] =
  121. "\n"
  122. "  This is the manual browser " PROGVERSION " (" PROGDATE "), " CPU " version\n"
  123. #ifdef V39
  124. "  This executable was compiled for AmigaOS 3.0 (V39) and up.\n"
  125. #endif
  126. "  Copyright © 1994 Christian Stieber\n"
  127. "\n"
  128. "\n"
  129. "  This program is free software; you can redistribute it and/or modify\n"
  130. "  it under the terms of the @{\x22GNU General Public License\x22 LINK COPYING/Main} as published by\n"
  131. "  the Free Software Foundation; either version 2 of the License, or\n"
  132. "  (at your option) any later version.\n"
  133. "\n"
  134. "  This program is distributed in the hope that it will be useful,\n"
  135. "  but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
  136. "  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
  137. "  @{\x22GNU General Public License\x22 LINK COPYING/Main} for more details.\n"
  138. "\n"
  139. "  You should have received a copy of the @{\x22GNU General Public License\x22 LINK COPYING/Main}\n"
  140. "  along with this program; if not, write to the Free Software\n"
  141. "  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n"
  142. "\n"
  143. "\n"
  144. "  Author: Christian Stieber\n"
  145. "          Konradstraße 41\n"
  146. "          D-85055 Ingolstadt\n"
  147. "          (Germany)\n"
  148. "\n"
  149. "  Currently (1994) I'm a student and may reached at the following address:\n"
  150. "\n"
  151. "          Christian Stieber\n"
  152. "          Seitzstraße 6, Zi. 306\n"
  153. "          D-80538 München\n"
  154. "          (Germany)\n"
  155. "\n"
  156. "          EMail: stieber@informatik.tu-muenchen.de\n"
  157. "\n";
  158.  
  159. /************************************************************************/
  160.  
  161. struct DirNode
  162.   {
  163.     struct DirNode *Next;
  164.     struct ActionNode *ActionNode;
  165.     char Name[1];
  166.   };
  167.  
  168. /************************************************************************/
  169.  
  170. static struct DirNode *DirectoryList;
  171. static struct DirNode *FileList;
  172. static char *NodeData;
  173. static ULONG NodeLength;
  174.  
  175. static char *MessageText;
  176.  
  177. #ifdef __GNUC__
  178. static struct FileInfoBlock FileInfoBlock __attribute__ ((aligned (4)));
  179. #else
  180. static struct FileInfoBlock __aligned FileInfoBlock;
  181. #endif
  182.  
  183. static struct ActionNode *LocalActionList;
  184.  
  185. /************************************************************************/
  186.  
  187. static void 
  188. InsertDirNode (struct DirNode *DirNode, struct DirNode **DirList)
  189.  
  190. {
  191.   if (!*DirList)
  192.     {
  193.       *DirList = DirNode;
  194.       DirNode->Next = NULL;
  195.     }
  196.   else
  197.     {
  198.       struct DirNode *Prev, *Current;
  199.  
  200.       Prev = (struct DirNode *) DirList;
  201.       Current = Prev->Next;
  202.       while (Current && (Stricmp (Current->Name, DirNode->Name) < 0))
  203.     {
  204.       Prev = Current;
  205.       Current = Current->Next;
  206.     }
  207.       Prev->Next = DirNode;
  208.       DirNode->Next = Current;
  209.     }
  210. }
  211.  
  212. /************************************************************************/
  213.  
  214. static void 
  215. FreeDirNodes (struct DirNode **DirList)
  216.  
  217. {
  218.   while (*DirList)
  219.     {
  220.       struct DirNode *Next;
  221.       Next = (*DirList)->Next;
  222.       Free (*DirList);
  223.       *DirList = Next;
  224.     }
  225. }
  226.  
  227. /************************************************************************/
  228. /*                                                                      */
  229. /* Look for an action node matching a given filename.                   */
  230. /* Checks the local list first, followed by the global list.            */
  231. /* Returns NULL for "no action assigned"                                */
  232. /*                                                                      */
  233. /************************************************************************/
  234.  
  235. static struct ActionNode *
  236. FindActionNode (char *Filename)
  237.  
  238. {
  239.   struct ActionNode *ActionNode;
  240.  
  241.   for (ActionNode = LocalActionList; ActionNode; ActionNode = ActionNode->Next)
  242.     {
  243.       if (MatchPatternNoCase (ActionNode->Pattern, Filename))
  244.     {
  245.       return ActionNode;
  246.     }
  247.     }
  248.  
  249.   for (ActionNode = ActionList; ActionNode; ActionNode = ActionNode->Next)
  250.     {
  251.       if (MatchPatternNoCase (ActionNode->Pattern, Filename))
  252.     {
  253.       return ActionNode;
  254.     }
  255.     }
  256.  
  257.   return NULL;
  258. }
  259.  
  260. /************************************************************************/
  261. /*                                                                      */
  262. /* Free the local action list                                           */
  263. /*                                                                      */
  264. /************************************************************************/
  265.  
  266. static void 
  267. FreeLocalActionList (void)
  268.  
  269. {
  270.   while (LocalActionList)
  271.     {
  272.       struct ActionNode *ThisNode;
  273.  
  274.       ThisNode = LocalActionList;
  275.       LocalActionList = ThisNode->Next;
  276.       Free (ThisNode);
  277.     }
  278. }
  279.  
  280. /************************************************************************/
  281. /*                                                                      */
  282. /* Read the local action list for a directory, if available.            */
  283. /*                                                                      */
  284. /************************************************************************/
  285.  
  286. static void 
  287. ReadLocalConfig (BPTR DirLock)
  288.  
  289. {
  290.   BPTR OldCurrDir;
  291.   BPTR FileHandle;
  292.  
  293.   OldCurrDir = CurrentDir (DirLock);
  294.   if (FileHandle = Open (CONFIG_NAME, MODE_OLDFILE))
  295.     {
  296.       int Result;
  297.       Result = ReadConfigFile (FileHandle, &LocalActionList);
  298.       Close (FileHandle);
  299.       if (!Result)
  300.     {
  301.       FreeLocalActionList ();
  302.     }
  303.     }
  304.   CurrentDir (OldCurrDir);
  305. }
  306.  
  307. /************************************************************************/
  308. /*                                                                      */
  309. /*                                                                      */
  310. /************************************************************************/
  311.  
  312. #define BUFFER_SIZE (4*1024)
  313.  
  314. static long 
  315. ReadDir (BPTR DirLock)
  316.  
  317. {
  318.   struct ExAllControl *ExAllControl;
  319.   long DosError;
  320.  
  321.   DosError = 0;
  322.   if ((ExAllControl = AllocDosObject (DOS_EXALLCONTROL, NULL)))
  323.     {
  324.       struct ExAllData *Buffer;
  325.       if ((Buffer = Malloc (BUFFER_SIZE)))
  326.     {
  327.       int more;
  328.       ReadLocalConfig (DirLock);
  329.       ExAllControl->eac_LastKey = 0;
  330.       ExAllControl->eac_MatchString = NULL;
  331.       ExAllControl->eac_MatchFunc = NULL;
  332.       do
  333.         {
  334.           more = ExAll (DirLock, Buffer, BUFFER_SIZE, ED_TYPE, ExAllControl);
  335.           if ((!more) && (IoErr () != ERROR_NO_MORE_ENTRIES))
  336.         {
  337.           DosError = IoErr ();
  338.         }
  339.           else
  340.         {
  341.           if (ExAllControl->eac_Entries)
  342.             {
  343.               struct ExAllData *ExAllData;
  344.               ExAllData = Buffer;
  345.               do
  346.             {
  347.               if (Stricmp (ExAllData->ed_Name, MESSAGE_NAME) || Stricmp (ExAllData->ed_Name, CONFIG_NAME))
  348.                 {
  349.                   struct ActionNode *ActionNode;
  350.                   ActionNode = FindActionNode (ExAllData->ed_Name);
  351.                   if (!ActionNode || Stricmp (ActionNode->Action, "IGNORE"))
  352.                 {
  353.                   struct DirNode *DirNode;
  354.                   if (ActionNode && !Stricmp (ActionNode->Action, "DEFAULT"))
  355.                     {
  356.                       ActionNode = NULL;
  357.                     }
  358.                   if ((DirNode = Malloc (sizeof (struct DirNode) + strlen (ExAllData->ed_Name))))
  359.                     {
  360.                       DirNode->ActionNode = ActionNode;
  361.                       strcpy (DirNode->Name, ExAllData->ed_Name);
  362.                       if (ExAllData->ed_Type == ST_SOFTLINK)
  363.                     {
  364.                       BPTR LinkLock;
  365.                       BPTR OldCurrDir;
  366.                       OldCurrDir = CurrentDir (DirLock);
  367.                       if ((LinkLock = Lock (ExAllData->ed_Name, SHARED_LOCK)))
  368.                         {
  369.                           if (Examine (LinkLock, &FileInfoBlock))
  370.                         {
  371.                           InsertDirNode (DirNode, FileInfoBlock.fib_DirEntryType >= 0 ? &DirectoryList : &FileList);
  372.                         }
  373.                           UnLock (LinkLock);
  374.                         }
  375.                       CurrentDir (OldCurrDir);
  376.                     }
  377.                       else
  378.                     {
  379.                       InsertDirNode (DirNode, ExAllData->ed_Type >= 0 ? &DirectoryList : &FileList);
  380.                     }
  381.                     }
  382.                   else
  383.                     {
  384.                       DosError = IoErr ();
  385.                     }
  386.                 }
  387.                 }
  388.               ExAllData = ExAllData->ed_Next;
  389.             }
  390.               while (!DosError && ExAllData);
  391.             }
  392.         }
  393.         }
  394.       while (!DosError && more);
  395.       if (more)
  396.         {
  397. #ifdef V39
  398.           ExAllEnd (DirLock, Buffer, BUFFER_SIZE, ED_TYPE, ExAllControl);
  399. #else
  400.           while (ExAll (DirLock, Buffer, BUFFER_SIZE, ED_TYPE, ExAllControl));
  401. #endif
  402.         }
  403.       if (DosError)
  404.         {
  405.           FreeDirNodes (&DirectoryList);
  406.           FreeDirNodes (&FileList);
  407.         }
  408.       Free (Buffer);
  409.       FreeLocalActionList ();
  410.     }
  411.       else
  412.     {
  413.       DosError = IoErr ();
  414.     }
  415.       FreeDosObject (DOS_EXALLCONTROL, ExAllControl);
  416.     }
  417.   else
  418.     {
  419.       DosError = IoErr ();
  420.     }
  421.   return DosError;
  422. }
  423.  
  424. #undef BUFFER_SIZE
  425.  
  426. /***********************************************/
  427.  
  428. static char *NodeDataTmp;
  429.  
  430. static int 
  431. PrintNodeText (char *Text)
  432.  
  433. {
  434.   if (NodeDataTmp)
  435.     {
  436.       NodeDataTmp = Stpcpy (NodeDataTmp, Text);
  437.     }
  438.   return strlen (Text);
  439. }
  440.  
  441. /***********************************************/
  442.  
  443. static int 
  444. PrintDir (char *ThisDir, char *PathName)
  445.  
  446. {
  447.   int Length;
  448.   struct DirNode *Current;
  449.   short ColWidth, Columns;
  450.   short MaxLength;
  451.   short Column;
  452.  
  453.   /* Max. length of the buttons */
  454.   MaxLength = 0;
  455.   for (Current = DirectoryList; Current; Current = Current->Next)
  456.     {
  457.       Length = strlen (Current->Name) + 1;
  458.       if (Length > MaxLength)
  459.     MaxLength = Length;
  460.     }
  461.   for (Current = FileList; Current; Current = Current->Next)
  462.     {
  463.       Length = strlen (Current->Name);
  464.       if (Length > MaxLength)
  465.     MaxLength = Length;
  466.     }
  467.   if (AmigaGuideBase->lib_Version >= 39)
  468.     MaxLength++;
  469.  
  470.   Columns = LineLength / (MaxLength + 1);
  471.   ColWidth = LineLength / Columns;
  472.   if (AmigaGuideBase->lib_Version >= 39)
  473.     ColWidth--;
  474.  
  475.   Length = 0;
  476.  
  477.   Column = 0;
  478.   for (Current = DirectoryList; Current; Current = Current->Next)
  479.     {
  480.       int CurWidth;
  481.       CurWidth = 0;
  482.       Length += PrintNodeText ("@{\x22");
  483.       CurWidth += PrintNodeText (Current->Name);
  484.       CurWidth += PrintNodeText ("/");
  485.       Length += PrintNodeText ("\x22 LINK \x22");
  486.       if (*ThisDir)
  487.     {
  488.       Length += PrintNodeText (ThisDir);
  489.       Length += PrintNodeText ("/");
  490.     }
  491.       Length += PrintNodeText (Current->Name);
  492.       Length += PrintNodeText ("\x22}");
  493.       Column++;
  494.       if (Column >= Columns)
  495.     {
  496.       Length += PrintNodeText ("\n");
  497.       Column = 0;
  498.     }
  499.       else
  500.     {
  501.       while (CurWidth < ColWidth)
  502.         CurWidth += PrintNodeText (" ");
  503.     }
  504.       Length += CurWidth;
  505.     }
  506.   if (Column)
  507.     {
  508.       Length += PrintNodeText ("\n");
  509.     }
  510.  
  511.   if (DirectoryList && FileList)
  512.     {
  513.       Length += PrintNodeText ("\n\n");
  514.     }
  515.  
  516.   Column = 0;
  517.   for (Current = FileList; Current; Current = Current->Next)
  518.     {
  519.       int CurWidth;
  520.       CurWidth = 0;
  521.       Length += PrintNodeText ("@{\x22");
  522.       CurWidth += PrintNodeText (Current->Name);
  523.       Length += PrintNodeText ("\x22 ");
  524.       if (Current->ActionNode)
  525.     {
  526.       char *t;
  527.       char x[4];
  528.  
  529.       x[1] = '\0';
  530.       for (t = Current->ActionNode->Action; *t; t++)
  531.         {
  532.           if (*t == '%')
  533.         {
  534.           switch (*(t + 1))
  535.             {
  536.             case '%':
  537.               Length += PrintNodeText ("%");
  538.               t++;
  539.               break;
  540.  
  541.             case 'p':
  542.               Length += PrintNodeText (PathName);
  543.               t++;
  544.               break;
  545.  
  546.             case 'f':
  547.               Length += PrintNodeText (Current->Name);
  548.               t++;
  549.               break;
  550.  
  551.             case 'F':
  552.               {
  553.             char *u, *v;
  554.             v = NULL;
  555.             for (u = Current->Name; *u; u++)
  556.               {
  557.                 if (*u == '.')
  558.                   v = u;
  559.               }
  560.             if (!v)
  561.               v = u;
  562.             for (u = Current->Name; u != v; u++)
  563.               {
  564.                 x[0] = *u;
  565.                 Length += PrintNodeText (x);
  566.               }
  567.               }
  568.               t++;
  569.               break;
  570.  
  571.             default:
  572.               x[0] = *t;
  573.               Length += PrintNodeText (x);
  574.               break;
  575.             }
  576.         }
  577.           else
  578.         {
  579.           x[0] = *t;
  580.           Length += PrintNodeText (x);
  581.         }
  582.         }
  583.     }
  584.       else
  585.     {
  586.       Length += PrintNodeText ("LINK \x22");
  587.       if (*ThisDir)
  588.         {
  589.           Length += PrintNodeText (ThisDir);
  590.           Length += PrintNodeText ("/");
  591.         }
  592.       Length += PrintNodeText (Current->Name);
  593.       Length += PrintNodeText ("/Main");
  594.       Length += PrintNodeText ("\x22");
  595.     }
  596.       Length += PrintNodeText ("}");
  597.       Column++;
  598.       if (Column >= Columns)
  599.     {
  600.       Length += PrintNodeText ("\n");
  601.       Column = 0;
  602.     }
  603.       else
  604.     {
  605.       while (CurWidth < ColWidth)
  606.         CurWidth += PrintNodeText (" ");
  607.     }
  608.       Length += CurWidth;
  609.     }
  610.   if (Column)
  611.     {
  612.       Length += PrintNodeText ("\n");
  613.     }
  614.  
  615.   return Length;
  616. }
  617.  
  618. /***********************************************/
  619.  
  620. static int 
  621. PrintMessage (void)
  622.  
  623. {
  624.   if (MessageText)
  625.     {
  626.       int Length;
  627.       Length = PrintNodeText (MessageText);
  628.       Length += PrintNodeText ("\n");
  629.       return Length;
  630.     }
  631.   return 0;
  632. }
  633.  
  634. /***********************************************/
  635.  
  636. static void 
  637. ReadMessage (BPTR DirLock)
  638.  
  639. {
  640.   BPTR OldCurrDir;
  641.   BPTR FileHandle;
  642.  
  643.   OldCurrDir = CurrentDir (DirLock);
  644.   if ((FileHandle = Open (MESSAGE_NAME, MODE_OLDFILE)))
  645.     {
  646.       if (ExamineFH (FileHandle, &FileInfoBlock))
  647.     {
  648.       ULONG Length;
  649.  
  650.       Length = FileInfoBlock.fib_Size + 1;
  651.       if (MessageText = Malloc (Length))
  652.         {
  653.           Read (FileHandle, MessageText, Length - 1);
  654.           MessageText[Length - 1] = '\0';
  655.         }
  656.     }
  657.       Close (FileHandle);
  658.     }
  659.   CurrentDir (OldCurrDir);
  660. }
  661.  
  662. /***********************************************/
  663.  
  664. #ifdef __GNUC__
  665. ULONG 
  666. AmigaGuideHostDispatcher (Msg Message)
  667. #else
  668. ULONG __saveds __asm 
  669. AmigaGuideHostDispatcher (register __a1 Msg Message)
  670. #endif
  671.  
  672. {
  673.   switch (Message->MethodID)
  674.     {
  675.     case HM_FINDNODE:
  676.       {
  677.     char *Name;
  678.  
  679.     Name = ((struct opFindHost *) Message)->ofh_Node;
  680.     while (!Strnicmp (Name, DatabaseName, strlen (DatabaseName)))
  681.       {
  682.         Name += strlen (DatabaseName) + 1;
  683.       }
  684.  
  685.     ((struct opFindHost *) Message)->ofh_Next = ((struct opFindHost *) Message)->ofh_Prev = ((struct opFindHost *) Message)->ofh_Node;
  686.  
  687.     if (!Stricmp ("main", Name))
  688.       {
  689.         ((struct opFindHost *) Message)->ofh_Title = "Manual browser " PROGVERSION;
  690.       }
  691.     else if (!strcmp ("AbOuT", Name))
  692.       {
  693.         ((struct opFindHost *) Message)->ofh_Title = "About the manual browser";
  694.       }
  695.     else
  696.       {
  697.         BPTR OldCurrDir;
  698.         BPTR TestLock;
  699.  
  700.         OldCurrDir = CurrentDir (ManDir);
  701.         if ((TestLock = Lock (Name, SHARED_LOCK)))
  702.           {
  703.         UnLock (TestLock);
  704.           }
  705.         CurrentDir (OldCurrDir);
  706.         if (!TestLock)
  707.           return FALSE;
  708.         ((struct opFindHost *) Message)->ofh_Title = Name;
  709.         ((struct opFindHost *) Message)->ofh_TOC = "main";
  710.       }
  711.     return TRUE;
  712.       }
  713.       break;
  714.  
  715.     case HM_OPENNODE:
  716.       {
  717.     BPTR DirLock;
  718.     BPTR OldCurrDir;
  719.     char *Name;
  720.     int Main;
  721.     long DosError;
  722.  
  723.     DosError = 0;
  724.     ((struct opNodeIO *) Message)->onm_Flags = HTNF_CLEAN;
  725.     ((struct opNodeIO *) Message)->onm_FileName = NULL;
  726.     Name = ((struct opNodeIO *) Message)->onm_Node;
  727.     while (!Strnicmp (Name, DatabaseName, strlen (DatabaseName)))
  728.       {
  729.         Name += strlen (DatabaseName) + 1;
  730.       }
  731.  
  732.     if ((Main = !Stricmp ("main", Name)))
  733.       {
  734.         Name += 4;
  735.       }
  736.     else if (!strcmp ("AbOuT", Name))
  737.       {
  738.         ((struct opNodeIO *) Message)->onm_DocBuffer = AboutText;
  739.         ((struct opNodeIO *) Message)->onm_BuffLen = sizeof (AboutText) - 1;
  740.         return TRUE;
  741.       }
  742.  
  743.     OldCurrDir = CurrentDir (ManDir);
  744.     if ((DirLock = Lock (Name, SHARED_LOCK)))
  745.       {
  746.         char *DirName;
  747.         int DirNameLength;
  748.  
  749.         DirNameLength = 256;
  750.         do
  751.           {
  752.         if (DirName = Malloc (DirNameLength))
  753.           {
  754.             if (NameFromLock (DirLock, DirName, DirNameLength))
  755.               {
  756.             break;
  757.               }
  758.             if (IoErr () != ERROR_LINE_TOO_LONG)
  759.               {
  760.             DosError = IoErr ();
  761.               }
  762.             Free (DirName);
  763.             DirName = NULL;
  764.             DirNameLength += 256;
  765.           }
  766.         else
  767.           {
  768.             DosError = IoErr ();
  769.           }
  770.           }
  771.         while (!DosError);
  772.         if (!DosError && !(DosError = ReadDir (DirLock)))
  773.           {
  774.         NodeDataTmp = NULL;
  775.         NodeLength = 0;
  776.         ReadMessage (DirLock);
  777.         NodeLength += PrintMessage ();
  778.         NodeLength += PrintDir (Name, DirName);
  779.         if (Main)
  780.           {
  781.             NodeLength += PrintNodeText ("\n\n"
  782.                          "@{\x22" "About the manual browser\x22 LINK \x22" "AbOuT\x22}\n");
  783.           }
  784.  
  785.         if ((NodeData = Malloc (NodeLength + 1)))
  786.           {
  787.             NodeDataTmp = NodeData;
  788.             PrintMessage ();
  789.             PrintDir (Name, DirName);
  790.             if (Main)
  791.               {
  792.             PrintNodeText ("\n\n"
  793.                        "@{\x22" "About the manual browser\x22 LINK \x22" "AbOuT\x22}\n");
  794.               }
  795.             ((struct opNodeIO *) Message)->onm_DocBuffer = NodeData;
  796.             ((struct opNodeIO *) Message)->onm_BuffLen = NodeLength;
  797.             UnLock (OldCurrDir);
  798.             OldCurrDir = DirLock;
  799.           }
  800.         else
  801.           {
  802.             DosError = IoErr ();
  803.           }
  804.         Free (MessageText);
  805.         MessageText = NULL;
  806.           }
  807.         if (!NodeData)
  808.           UnLock (DirLock);
  809.         if (DirName)
  810.           {
  811.         Free (DirName);
  812.           }
  813.       }
  814.     else
  815.       {
  816.         DosError = IoErr ();
  817.       }
  818.     CurrentDir (OldCurrDir);
  819.     if (DosError)
  820.       {
  821.         static char FaultString[84];
  822.         ((struct opNodeIO *) Message)->onm_DocBuffer = FaultString;
  823.         ((struct opNodeIO *) Message)->onm_BuffLen = Fault (DosError, NULL, FaultString, sizeof (FaultString));
  824.       }
  825.     return TRUE;
  826.       }
  827.       break;
  828.  
  829.     case HM_CLOSENODE:
  830.       {
  831.     if (NodeData)
  832.       Free (NodeData);
  833.     NodeData = NULL;
  834.     FreeDirNodes (&DirectoryList);
  835.     FreeDirNodes (&FileList);
  836.     return TRUE;
  837.       }
  838.       break;
  839.     }
  840.   return FALSE;
  841. }
  842.